﻿using System;
using System.Collections.Generic;
using System.Drawing;
using CI.Organism;

namespace CI.Mesopotamia.Neural
{
    /// <summary>
    /// Create a simple vision system which will notify on updates
    /// </summary>
    public class SimpleVisionSystem : IVisionSystem
    {
        public const decimal GreyscaleFromRed = 0.3m;
        public const decimal GreyscaleFromBlue = 0.11m;
        public const decimal GreyscaleFromGreen = 0.59m;


        public SVSFormatType FormatType { get; private set; }

        private readonly Dictionary<int, Dictionary<int, CoordinateListenerDelegate>> _coordinateListners = new Dictionary<int, Dictionary<int, CoordinateListenerDelegate>>();

        public SimpleVisionSystem(SVSFormatType formatType)
        {
            FormatType = formatType;
        }

        public void ProcessNewBitmap(Bitmap bitmap)
        {
            #region Argument check
            if (bitmap == null)
                throw new ArgumentException("bitmap");
            #endregion

            var widthOffset = (int)bitmap.Width / 2;
            var heightOffset = (int)bitmap.Height / 2;

            foreach (var x in _coordinateListners)
            {
                var y = x.Value;
                foreach (var key in y.Keys)
                {
                    var callback = y[key];
                    if (callback == null) continue;

                    var pixelColour = bitmap.GetPixel(x.Key + heightOffset, key + widthOffset);
                    var outputColour = FormatType == SVSFormatType.GreyScale
                                           ? ARGBtoGreyScale(pixelColour)
                                           : pixelColour.ToArgb();
                    callback(pixelColour, outputColour);
                }
            }

        }

        public void RegisterCooridanteListerner(int xCoordinate, int yCoordinate, CoordinateListenerDelegate callback)
        {
            #region Argument check
            if (callback == null)
                throw new ArgumentException("callback");
            #endregion

            Dictionary<int, CoordinateListenerDelegate> ykey;

            if (!_coordinateListners.TryGetValue(xCoordinate, out ykey))
            {
                ykey = new Dictionary<int, CoordinateListenerDelegate>();
                _coordinateListners[xCoordinate] = ykey;
            }

            if (!ykey.ContainsKey(yCoordinate))
            {
                ykey.Add(yCoordinate, callback);
            }
            else
            {
                ykey[yCoordinate] += callback;
            }

        }

        public void UnregisterCoordinateListener(int xCoordinate, int yCoordinate, CoordinateListenerDelegate callback)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Caclcuate the greyscale value from ARGB
        /// </summary>
        /// <param name="argbColour"></param>
        /// <returns></returns>
        public static long ARGBtoGreyScale(Color argbColour)
        {
            long grayScale = (int)((argbColour.R * .3) + (argbColour.G * .59) + (argbColour.B * .11));
            return grayScale;
        }
    }


}
